/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.rantipin.media;

import java.awt.Component;
import java.awt.Dimension;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Format;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;
import ru.rantipin.utilities.ReflectionMediaData;

/**
 *
 * @author rantipin
 */
public class MediaHelper {
    
    public int getDeviceIndex(String deviceName) {
        Vector dev = CaptureDeviceManager.getDeviceList(new VideoFormat("RGB"));
        for(int i = 0; i < dev.size(); ++i) {
            CaptureDeviceInfo info = (CaptureDeviceInfo)dev.elementAt(i);
            if (info.getName().equals(deviceName)) {
                return i;
            }
        }
        
        return -1;
    }
    
    public Set<String> getDeviceInfo() {
        Vector dev = CaptureDeviceManager.getDeviceList(new VideoFormat("RGB"));
        
        TreeSet<String> names = new TreeSet<String>();
        for(int i = 0; i < dev.size(); ++i) {
            CaptureDeviceInfo info = (CaptureDeviceInfo)dev.elementAt(i);
            names.add(info.getName());
            devices.put(info.getName(), getFormat4Device(info));
        }
        
        return  names;
    }
    
    private TreeMap<String, TreeMap<String, RGBFormat>> getFormat4Device(CaptureDeviceInfo info) {
        Format[] formats = info.getFormats();
        TreeMap<String, TreeMap<String, RGBFormat>> map = new TreeMap<String, TreeMap<String, RGBFormat>>();
        
        for(int i = 0; i < formats.length; ++i) {
            Format format = formats[i];
            
            if (format instanceof RGBFormat) {
                RGBFormat rgb = (RGBFormat)format;
                
                Dimension dimension = rgb.getSize();
                String formatSize = Math.round(dimension.getWidth()) + "x" + Math.round(dimension.getHeight());
                String bitPerPixel = String.valueOf(rgb.getBitsPerPixel());
                
                TreeMap<String, RGBFormat> mapBits = map.get(formatSize);
                if (mapBits == null) {
                    mapBits = new TreeMap<String, RGBFormat>();
                    map.put(formatSize, mapBits);
                }
                mapBits.put(bitPerPixel, rgb);
            }
        }
        
        return map;
    }
    
    public Set<String> getSize(String deviceName) {
        TreeMap<String, TreeMap<String, RGBFormat>> sizeMap = devices.get(deviceName);
        return sizeMap != null? sizeMap.keySet(): new TreeSet<String>();
    }
    
    public Set<String> getBitsPerPixel(String deviceName, String size) {
        TreeMap<String, TreeMap<String, RGBFormat>> sizeMap = devices.get(deviceName);
        if (sizeMap != null) {
            TreeMap<String, RGBFormat> bitsMap =  sizeMap.get(size);
            if (bitsMap != null) {
                return bitsMap.keySet();
            }
        }
        
        return new TreeSet<String>();
    }
    
    public void setInitCaptureDevice(String deviceName, String size, String bitsPerPixel, ReflectionMediaData reflection) throws MediaProcessorException {
        if (!"".equals(deviceName) && !"".equals(size) && !"".equals(bitsPerPixel)) {
            captureFormat = devices.get(deviceName).get(size).get(bitsPerPixel);
            Logger.getLogger(MediaHelper.class.getName()).log(Level.INFO, captureFormat.toString());
            
            stopMediaProcessor();
            
            mediaProcessor = new MediaProcessor(reflection);
            mediaProcessor.initialize(deviceName, captureFormat);
        }
    }
    
    public void setInitFile(String path, ReflectionMediaData reflection) throws MediaProcessorException {
        stopMediaProcessor();
                
        mediaProcessor = new MediaProcessor(reflection);
        mediaProcessor.initialize(path);
    }
    
    public Component getVisualComponent() throws MediaProcessorException {
        return mediaProcessor.getVisualComponent();
    }
    
    public Component getControlComponent() throws MediaProcessorException {
        return mediaProcessor.getControlComponent();
    }
    
    public void startMediaProcessor() {
        if (mediaProcessor != null) {
            mediaProcessor.startProcessor();
        }
    }
    
    public void stopMediaProcessor() {
        if (mediaProcessor != null) {
            mediaProcessor.stopProcessor();
        }
        mediaProcessor = null;
    }
    
    public void setMediabounds(MediaProcessor.MediaBounds mb) {
        if (mediaProcessor != null) {
            mediaProcessor.mediaBounds = mb;
        }
    }
    
    public void setUseForceBW(boolean bw) {
        if (mediaProcessor != null) {
            mediaProcessor.useblackwhite = bw;
        }
    }
    
    public static MediaHelper getInstance() {
        if (INSTANCE == null) {
            synchronized(MediaHelper.class) {
                if (INSTANCE == null) {
                    INSTANCE = new MediaHelper();
                }
            }
        }
        
        return INSTANCE;
    }
    
    
    
    private MediaProcessor mediaProcessor = null; 
    private RGBFormat captureFormat = null;
    private TreeMap<String, TreeMap<String, TreeMap<String, RGBFormat>>> devices = new TreeMap<String, TreeMap<String, TreeMap<String, RGBFormat>>>();
    
    private static volatile MediaHelper INSTANCE = null;
}
